/**
 * Copyright (c) 2006-2016, JGraph Ltd
 * Copyright (c) 2006-2016, Gaudenz Alder
 */
var mxResources =
    {
        /**
         * Class: mxResources
         *
         * Implements internationalization. You can provide any number of
         * resource files on the server using the following format for the
         * filename: name[-en].properties. The en stands for any lowercase
         * 2-character language shortcut (eg. de for german, fr for french).
         *
         * If the optional language extension is omitted, then the file is used as a
         * default resource which is loaded in all cases. If a properties file for a
         * specific language exists, then it is used to override the settings in the
         * default resource. All entries in the file are of the form key=value. The
         * values may then be accessed in code via <get>. Lines without
         * equal signs in the properties files are ignored.
         *
         * Resource files may either be added programmatically using
         * <add> or via a resource tag in the UI section of the
         * editor configuration file, eg:
         *
         * (code)
         * <mxEditor>
         *   <ui>
         *     <resource basename="examples/resources/mxWorkflow"/>
         * (end)
         *
         * The above element will load examples/resources/mxWorkflow.properties as well
         * as the language specific file for the current language, if it exists.
         *
         * Values may contain placeholders of the form {1}...{n} where each placeholder
         * is replaced with the value of the corresponding array element in the params
         * argument passed to <mxResources.get>. The placeholder {1} maps to the first
         * element in the array (at index 0).
         *
         * See <mxClient.language> for more information on specifying the default
         * language or disabling all loading of resources.
         *
         * Lines that start with a # sign will be ignored.
         *
         * Special characters
         *
         * To use unicode characters, use the standard notation (eg. \u8fd1) or %u as a
         * prefix (eg. %u20AC will display a Euro sign). For normal hex encoded strings,
         * use % as a prefix, eg. %F6 will display a "o umlaut" (&ouml;).
         *
         * See <resourcesEncoded> to disable this. If you disable this, make sure that
         * your files are UTF-8 encoded.
         *
         * Asynchronous loading
         *
         * By default, the core adds two resource files synchronously at load time.
         * To load these files asynchronously, set <mxLoadResources> to false
         * before loading mxClient.js and use <mxResources.loadResources> instead.
         *
         * Variable: resources
         *
         * Object that maps from keys to values.
         */
        resources: {},

        /**
         * Variable: extension
         *
         * Specifies the extension used for language files. Default is <mxResourceExtension>.
         */
        extension: mxResourceExtension,

        /**
         * Variable: resourcesEncoded
         *
         * Specifies whether or not values in resource files are encoded with \u or
         * percentage. Default is false.
         */
        resourcesEncoded: false,

        /**
         * Variable: loadDefaultBundle
         *
         * Specifies if the default file for a given basename should be loaded.
         * Default is true.
         */
        loadDefaultBundle: true,

        /**
         * Variable: loadDefaultBundle
         *
         * Specifies if the specific language file file for a given basename should
         * be loaded. Default is true.
         */
        loadSpecialBundle: true,

        /**
         * Function: isLanguageSupported
         *
         * Hook for subclassers to disable support for a given language. This
         * implementation returns true if lan is in <mxClient.languages>.
         *
         * Parameters:
         *
         * lan - The current language.
         */
        isLanguageSupported: function(lan)
        {
            if (mxClient.languages != null)
            {
                return mxUtils.indexOf(mxClient.languages, lan) >= 0;
            }

            return true;
        },

        /**
         * Function: getDefaultBundle
         *
         * Hook for subclassers to return the URL for the special bundle. This
         * implementation returns basename + <extension> or null if
         * <loadDefaultBundle> is false.
         *
         * Parameters:
         *
         * basename - The basename for which the file should be loaded.
         * lan - The current language.
         */
        getDefaultBundle: function(basename, lan)
        {
            if (mxResources.loadDefaultBundle || !mxResources.isLanguageSupported(lan))
            {
                return basename + mxResources.extension;
            }
            else
            {
                return null;
            }
        },

        /**
         * Function: getSpecialBundle
         *
         * Hook for subclassers to return the URL for the special bundle. This
         * implementation returns basename + '_' + lan + <extension> or null if
         * <loadSpecialBundle> is false or lan equals <mxClient.defaultLanguage>.
         *
         * If <mxResources.languages> is not null and <mxClient.language> contains
         * a dash, then this method checks if <isLanguageSupported> returns true
         * for the full language (including the dash). If that returns false the
         * first part of the language (up to the dash) will be tried as an extension.
         *
         * If <mxResources.language> is null then the first part of the language is
         * used to maintain backwards compatibility.
         *
         * Parameters:
         *
         * basename - The basename for which the file should be loaded.
         * lan - The language for which the file should be loaded.
         */
        getSpecialBundle: function(basename, lan)
        {
            if (mxClient.languages == null || !this.isLanguageSupported(lan))
            {
                var dash = lan.indexOf('-');

                if (dash > 0)
                {
                    lan = lan.substring(0, dash);
                }
            }

            if (mxResources.loadSpecialBundle && mxResources.isLanguageSupported(lan) && lan != mxClient.defaultLanguage)
            {
                return basename + '_' + lan + mxResources.extension;
            }
            else
            {
                return null;
            }
        },

        /**
         * Function: add
         *
         * Adds the default and current language properties file for the specified
         * basename. Existing keys are overridden as new files are added. If no
         * callback is used then the request is synchronous.
         *
         * Example:
         *
         * At application startup, additional resources may be
         * added using the following code:
         *
         * (code)
         * mxResources.add('resources/editor');
         * (end)
         *
         * Parameters:
         *
         * basename - The basename for which the file should be loaded.
         * lan - The language for which the file should be loaded.
         * callback - Optional callback for asynchronous loading.
         */
        add: function(basename, lan, callback)
        {
            lan = (lan != null) ? lan : ((mxClient.language != null) ?
                mxClient.language.toLowerCase() : mxConstants.NONE);

            if (lan != mxConstants.NONE)
            {
                var defaultBundle = mxResources.getDefaultBundle(basename, lan);
                var specialBundle = mxResources.getSpecialBundle(basename, lan);

                var loadSpecialBundle = function()
                {
                    if (specialBundle != null)
                    {
                        if (callback)
                        {
                            mxUtils.get(specialBundle, function(req)
                            {
                                mxResources.parse(req.getText());
                                callback();
                            }, function()
                            {
                                callback();
                            });
                        }
                        else
                        {
                            try
                            {
                                var req = mxUtils.load(specialBundle);

                                if (req.isReady())
                                {
                                    mxResources.parse(req.getText());
                                }
                            }
                            catch (e)
                            {
                                // ignore
                            }
                        }
                    }
                    else if (callback != null)
                    {
                        callback();
                    }
                }

                if (defaultBundle != null)
                {
                    if (callback)
                    {
                        mxUtils.get(defaultBundle, function(req)
                        {
                            mxResources.parse(req.getText());
                            loadSpecialBundle();
                        }, function()
                        {
                            loadSpecialBundle();
                        });
                    }
                    else
                    {
                        try
                        {
                            var req = mxUtils.load(defaultBundle);

                            if (req.isReady())
                            {
                                mxResources.parse(req.getText());
                            }

                            loadSpecialBundle();
                        }
                        catch (e)
                        {
                            // ignore
                        }
                    }
                }
                else
                {
                    // Overlays the language specific file (_lan-extension)
                    loadSpecialBundle();
                }
            }
        },

        /**
         * Function: parse
         *
         * Parses the key, value pairs in the specified
         * text and stores them as local resources.
         */
        parse: function(text)
        {
            if (text != null)
            {
                var lines = text.split('\n');

                for (var i = 0; i < lines.length; i++)
                {
                    if (lines[i].charAt(0) != '#')
                    {
                        var index = lines[i].indexOf('=');

                        if (index > 0)
                        {
                            var key = lines[i].substring(0, index);
                            var idx = lines[i].length;

                            if (lines[i].charCodeAt(idx - 1) == 13)
                            {
                                idx--;
                            }

                            var value = lines[i].substring(index + 1, idx);

                            if (this.resourcesEncoded)
                            {
                                value = value.replace(/\\(?=u[a-fA-F\d]{4})/g,"%");
                                mxResources.resources[key] = unescape(value);
                            }
                            else
                            {
                                mxResources.resources[key] = value;
                            }
                        }
                    }
                }
            }
        },

        /**
         * Function: get
         *
         * Returns the value for the specified resource key.
         *
         * Example:
         * To read the value for 'welomeMessage', use the following:
         * (code)
         * var result = mxResources.get('welcomeMessage') || '';
         * (end)
         *
         * This would require an entry of the following form in
         * one of the English language resource files:
         * (code)
         * welcomeMessage=Welcome to mxGraph!
         * (end)
         *
         * The part behind the || is the string value to be used if the given
         * resource is not available.
         *
         * Parameters:
         *
         * key - String that represents the key of the resource to be returned.
         * params - Array of the values for the placeholders of the form {1}...{n}
         * to be replaced with in the resulting string.
         * defaultValue - Optional string that specifies the default return value.
         */
        get: function(key, params, defaultValue)
        {
            var value = mxResources.resources[key];

            // Applies the default value if no resource was found
            if (value == null)
            {
                value = defaultValue;
            }

            // Replaces the placeholders with the values in the array
            if (value != null && params != null)
            {
                value = mxResources.replacePlaceholders(value, params);
            }

            return value;
        },

        /**
         * Function: replacePlaceholders
         *
         * Replaces the given placeholders with the given parameters.
         *
         * Parameters:
         *
         * value - String that contains the placeholders.
         * params - Array of the values for the placeholders of the form {1}...{n}
         * to be replaced with in the resulting string.
         */
        replacePlaceholders: function(value, params)
        {
            var result = [];
            var index = null;

            for (var i = 0; i < value.length; i++)
            {
                var c = value.charAt(i);

                if (c == '{')
                {
                    index = '';
                }
                else if (index != null && 	c == '}')
                {
                    index = parseInt(index)-1;

                    if (index >= 0 && index < params.length)
                    {
                        result.push(params[index]);
                    }

                    index = null;
                }
                else if (index != null)
                {
                    index += c;
                }
                else
                {
                    result.push(c);
                }
            }

            return result.join('');
        },

        /**
         * Function: loadResources
         *
         * Loads all required resources asynchronously. Use this to load the graph and
         * editor resources if <mxLoadResources> is false.
         *
         * Parameters:
         *
         * callback - Callback function for asynchronous loading.
         */
        loadResources: function(callback)
        {
            mxResources.add(mxClient.basePath+'/resources/editor', null, function()
            {
                mxResources.add(mxClient.basePath+'/resources/graph', null, callback);
            });
        }

    };
